Excess mortality & voting patterns in CH

Ancillary data preparation

Population

Data extracted from px-x-0103010000_201:

Ständige und nichtständige Wohnbevölkerung nach institutionellen Gliederungen, Staatsangehörigkeit (Kategorie), Geburtsort, Geschlecht und Altersklasse

Important info from footnotes:

Letzte Änderungen: Neuer Datensatz (Jahr 2020) Stand der Datenbank: Juni 2021 Stichtag: 31. Dezember Raumbezug: Gemeinden / 18.10.2020 Datenquelle: Statistik der Bevölkerung und der Haushalte STATPOP Definition der ständigen Wohnbevölkerung

Community codes

Community mutations data after 2021-01-01 from BfS are integrated into the data and pops are recalculated using these new codes to match mortality.

histcomm <- read_rds("data/BfS/histcomm.Rds") %>% 
  filter(datum_der_aufnahme >= ymd("2021-01-01")) %>% 
  select(bfs_gde_num_old, bfs_gde_num_new, gemeindename_new)

Further corrections of municipalities mutations are needed to bring the data to the state of 2022-01-01.

Data preps

Data aggregated to age groups as in deaths dataset.

pop <- read_xlsx("data-raw/BfS/px-x-0103010000_201.xlsx", 
                 col_types = c("numeric", 
                               "skip", "numeric", "text", "skip", 
                               "skip", "skip", "text", "skip", "skip", 
                               "skip", "text", "numeric", "numeric", 
                               "numeric", "numeric", "numeric", 
                               "numeric", "numeric", "numeric", 
                               "numeric", "numeric", "numeric", 
                               "numeric", "numeric", "numeric", 
                               "numeric", "numeric", "numeric", 
                               "numeric", "numeric", "numeric", 
                               "numeric"), 
                 skip = 1) %>%
  remove_empty(c("rows", "cols")) %>% clean_names() %>% 
  rename(year = x1, 
         GMDNR = x2,
         GMDNAME = x3) %>% 
  mutate(sex = if_else(x5 == "Frau", "Female", "Male"),
         nationality = if_else(x4 == "Schweiz", "Swiss", "Foreigner"),
         year = as.integer(year)) %>% 
  select(-x4, -x5) %>% 
  relocate(sex, .after = GMDNAME) %>% 
  relocate(nationality, .after = sex) %>% 
  mutate(GMDNAME = word(GMDNAME, 2, -1)) %>% 
  fill(year, GMDNR, GMDNAME, nationality) %>% 
  mutate(`<40` = x0_4_jahre + x5_9_jahre + x10_14_jahre + x15_19_jahre + 
           x20_24_jahre + x25_29_jahre + x30_34_jahre + x35_39_jahre) %>% 
  select(-x0_4_jahre, -x5_9_jahre, -x10_14_jahre, -x15_19_jahre,  
         -x20_24_jahre, -x25_29_jahre, -x30_34_jahre, -x35_39_jahre) %>% 
  mutate(`40-49` = x40_44_jahre + x45_49_jahre) %>% 
  mutate(`50-59` = x50_54_jahre + x55_59_jahre) %>% 
  mutate(`60-69` = x60_64_jahre + x65_69_jahre) %>% 
  mutate(`70-79` = x70_74_jahre + x75_79_jahre) %>% 
  select(-x40_44_jahre, -x45_49_jahre, -x50_54_jahre, -x55_59_jahre,
         -x60_64_jahre, -x65_69_jahre, -x70_74_jahre, -x75_79_jahre) %>% 
  mutate(`80+` = x80_84_jahre +x85_89_jahre + x90_94_jahre +
           x95_99_jahre + x100_jahre_und_mehr) %>% 
  select(-x80_84_jahre, -x85_89_jahre, -x90_94_jahre,
         -x95_99_jahre, -x100_jahre_und_mehr) %>% 
  pivot_longer(cols = `<40`:`80+`, 
               names_to = "age", values_to = "pop") %>% 
  
  # BfS identified changes
  left_join(histcomm, by = c("GMDNR" = "bfs_gde_num_old")) %>% 
  mutate(GMDNR = if_else(!is.na(bfs_gde_num_new), bfs_gde_num_new, GMDNR),
         GMDNAME = if_else(!is.na(gemeindename_new), gemeindename_new, GMDNAME)) %>% 
  select(-bfs_gde_num_new, -gemeindename_new) %>% 
  
  # Essertes merge
  mutate(GMDNR = if_else(GMDNAME == "Essertes", 5805, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Essertes", "Oron", GMDNAME)) %>% 
  
  # now to reach the state of `2022-01-01`
  mutate(GMDNR = if_else(GMDNAME == "Bad Zurzach", 4324, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Bad Zurzach", "Zurzach", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Baldingen", 4324, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Baldingen", "Zurzach", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Böbikon", 4324, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Böbikon", "Zurzach", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Kaiserstuhl", 4324, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Kaiserstuhl", "Zurzach", GMDNAME)) %>%
  mutate(GMDNR = if_else(GMDNAME == "Rekingen (AG)", 4324, GMDNR)) %>%
  mutate(GMDNAME = if_else(GMDNAME == "Rekingen (AG)", "Zurzach", GMDNAME)) %>%
  mutate(GMDNR = if_else(GMDNAME == "Rietheim", 4324, GMDNR)) %>%
  mutate(GMDNAME = if_else(GMDNAME == "Rietheim", "Zurzach", GMDNAME)) %>%
  mutate(GMDNR = if_else(GMDNAME == "Rümikon", 4324, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Rümikon", "Zurzach", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Wislikofen", 4324, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Wislikofen", "Zurzach", GMDNAME)) %>% 
  # Böztal merge
  mutate(GMDNR = if_else(GMDNAME == "Bözen", 4185, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Bözen", "Böztal", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Elfingen", 4185, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Elfingen", "Böztal", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Effingen", 4185, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Effingen", "Böztal", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Hornussen", 4185, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Hornussen", "Böztal", GMDNAME)) %>% 
  # Blonay - Saint-Légier merge
  mutate(GMDNR = if_else(GMDNAME == "Blonay", 5892, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Blonay", "Blonay - Saint-Légier", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Saint-Légier-La Chiésaz", 5892, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Saint-Légier-La Chiésaz", "Blonay - Saint-Légier", GMDNAME)) %>% 
  # Murten merge
  mutate(GMDNR = if_else(GMDNAME == "Galmiz", 2275, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Galmiz", "Murten", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Gempenach", 2275, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Gempenach", "Murten", GMDNAME)) %>% 
  mutate(GMDNR = if_else(GMDNAME == "Clavaleyres", 2275, GMDNR)) %>% 
  mutate(GMDNAME = if_else(GMDNAME == "Clavaleyres", "Murten", GMDNAME)) %>% 
  
  group_by(year, GMDNR, GMDNAME, sex, age) %>% 
  summarise(pop = as.integer(sum(pop))) %>% 
  ungroup() %>% 
  arrange(year, GMDNR, sex, age)

Yearly totals (on 31st Dec!):

# A tibble: 7 × 2
   year pop      
  <int> <chr>    
1  2014 8,237,666
2  2015 8,327,126
3  2016 8,419,550
4  2017 8,484,130
5  2018 8,544,527
6  2019 8,606,033
7  2020 8,670,300

Age (40 plus!) distributions over years

Predicting 2020 population

For each age, sex, nationality stratum, for each municipality separately, Poisson model was fitted using the 2014-2019 data; then prediction was made for 2020 & 2021 years. The gist of this operation was to exclude the effect of pandemic from the pop counts in years affected.

pop_ext_poi <- pop %>% 
  filter(year != 2020) %>% 
  # filter(GMDNR == 261 | GMDNR == 389) %>%
  group_by(GMDNR, age, sex) %>% 
  do(glm(pop ~ year, data = ., family = "poisson") %>%
       predict(., newdata = tibble(year = as.integer(2020)), type = "response") %>%
       tibble(year = as.integer(2020), pop_ext_poi = .)) %>% 
  ungroup() %>% 
  mutate(pop_ext_poi = as.integer(round(pop_ext_poi))) %>% 
  arrange(year, GMDNR, sex, age) %>% 
  relocate(year)

Summary of values:

   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
      0      42     108     338     283  117341       2 

Note: 2 NAs!

# A tibble: 7 × 6
   year GMDNR GMDNAME sex   age     pop
  <int> <dbl> <chr>   <chr> <chr> <int>
1  2014  4232 Geltwil Male  80+       0
2  2015  4232 Geltwil Male  80+       0
3  2016  4232 Geltwil Male  80+       0
4  2017  4232 Geltwil Male  80+       0
5  2018  4232 Geltwil Male  80+       0
6  2019  4232 Geltwil Male  80+       1
7  2020  4232 Geltwil Male  80+       3
# A tibble: 1 × 5
   year GMDNR age   sex   pop_ext_poi
  <int> <dbl> <chr> <chr>       <int>
1  2020  4232 80+   Male           NA
# A tibble: 7 × 6
   year GMDNR GMDNAME   sex   age     pop
  <int> <dbl> <chr>     <chr> <chr> <int>
1  2014   389 Meienried Male  80+       0
2  2015   389 Meienried Male  80+       0
3  2016   389 Meienried Male  80+       0
4  2017   389 Meienried Male  80+       0
5  2018   389 Meienried Male  80+       0
6  2019   389 Meienried Male  80+       1
7  2020   389 Meienried Male  80+       1
# A tibble: 1 × 5
   year GMDNR age   sex   pop_ext_poi
  <int> <dbl> <chr> <chr>       <int>
1  2020   389 80+   Male           NA

Results in large municipality

Results for large municipality are fine. Predictions are in red.

For small municipality we might end up with sth more wiggly.

Note: lack of prediction for 2020 & 2021 for oldest males!

There are two municipalities with missing predictions for oldest males:

# A tibble: 2 × 4
  GMDNR age   sex   GMDNAME  
  <dbl> <chr> <chr> <chr>    
1   389 80+   Male  Meienried
2  4232 80+   Male  Geltwil  

Population in this strata was replaced by estimates of a simple linear model.

pop_complete <- pop %>% 
  
  # extrapolated 2020
  left_join(pop_ext_poi) %>% 
  mutate(pop_ext_poi = if_else(year < 2020, 
                               pop, pop_ext_poi)) %>% 
  
  # replacing poi missings with lm
  left_join(pop_ext_lm) %>% 
  mutate(pop_ext_poi = if_else(year >= 2020 & is.na(pop_ext_poi), 
                               pop_ext_lm, pop_ext_poi)) %>% 
  select(-pop_ext_lm) 

Getting mid-year pops

For each age, sex, nationality stratum, for each municipality separately, simple mean of the two years of data is used to estimate the middle point. In such case we use, for instance data from 31st Dec 2014 and 31st Dec 2015 to estimate pop mid-2015.

for (i in 2014:2019){
  
  result <- pop_complete %>% 
    filter(year >= i & year <= i + 1) %>% 
    # filter(GMDNR == 261 | GMDNR == 389) %>%
    group_by(GMDNR, age, sex) %>% 
    summarise(pop_mid_poi = mean(pop_ext_poi)) %>% 
    ungroup() %>% 
    mutate(year = as.integer(i + 1),
           pop_mid_poi = as.integer(round(pop_mid_poi))) %>% 
    arrange(GMDNR, sex, age) %>% 
    relocate(year)
  
  if (i == 2014) {
    pop_mid_poi <- result
  } else {
    pop_mid_poi <- bind_rows(pop_mid_poi, result)
  }
  
}

Large municipality

Again, results for large municipality are fine:

Small municipality

Again, for small municipality we might end up with sth more wiggly.

Deaths > pop problem

surplus <- w_deaths_2015_2020_year_pop %>% 
  filter(deaths > pop_mid_poi) %>% 
  arrange(GMDNR, year) %>% 
  mutate(difference = pop_mid_poi - deaths)

There are 20 strata from 19 communities where count of deaths is larger than count of pop. The difference is always 1 in plus over pop 0.

In all these cases pop was increased by 1 to match the count of deaths!

w_deaths_2015_2020_year_pop %<>% 
  mutate(pop_mid_poi = if_else(deaths > pop_mid_poi, deaths, pop_mid_poi))

Cartogram

2020 pop counts (ignoring age structure) were used to derive cartograms.

Communities & pops

R solution 1

Using cartogram package.

# takes a while!
carto <- carto_data %>%
  cartogram::cartogram_cont("pop")

write_rds(carto, "data/carto/carto.Rds")

carto_ncont <- carto_data %>% 
  cartogram::cartogram_ncont("pop")

write_rds(carto_ncont, "data/carto/carto_ncont.Rds")

carto_dorling <- carto_data %>% 
  cartogram::cartogram_dorling("pop")

write_rds(carto_dorling, "data/carto/carto_dorling.Rds")

R solution 2

Using cartogramR package.

carto_gsm <- carto_data %>%
  cartogramR::cartogramR(count = "pop", method = "gsm")

write_rds(carto_gsm, "data/carto/carto_gsm.Rds")

ScapeToad version

carto_data %>% 
  st_write("data/carto/in_gg.shp", delete_dsn = TRUE)

se %>% 
  select(GMDNR, GMDNAME) %>% 
  st_write("data/carto/in_se.shp", delete_dsn = TRUE)

# java -Xmx1g -jar "C:\Program Files\ScapeToad-v11\ScapeToad.jar"

‘Classic’ cartogram

Committee Member: 1(1) 2(1) 3(1) 4(1) 5(1) 6(1) 7(1) 8(1) 9(1) 10(1)
Computing Hierarchical Clustering

Noncontinuous cartogram

Committee Member: 1(1) 2(1) 3(1) 4(1) 5(1) 6(1) 7(1) 8(1) 9(1) 10(1)
Computing Hierarchical Clustering

Dorling carotgram

Committee Member: 1(1) 2(1) 3(1) 4(1) 5(1) 6(1) 7(1) 8(1) 9(1) 10(1)
Computing Hierarchical Clustering

Swiss-SEP

sep3 <- read_rds("../SNC_Swiss-SEP2/FINAL/RDS/ssep3_user_geo.Rds") %>%
  select(gisid, ssep3, ssep3_d) %>% 
  st_transform(crs = 2056)

Using 1,527,173 n’hoods from version 3.0:

ssep3_d <integer> 
# total N=1527173 valid N=1527173 mean=5.50 sd=2.87

Value |      N | Raw % | Valid % | Cum. %
-----------------------------------------
    1 | 152719 |    10 |      10 |     10
    2 | 152720 |    10 |      10 |     20
    3 | 152713 |    10 |      10 |     30
    4 | 152721 |    10 |      10 |     40
    5 | 152724 |    10 |      10 |     50
    6 | 152708 |    10 |      10 |     60
    7 | 152717 |    10 |      10 |     70
    8 | 152722 |    10 |      10 |     80
    9 | 152712 |    10 |      10 |     90
   10 | 152717 |    10 |      10 |    100
 <NA> |      0 |     0 |    <NA> |   <NA>

This is aggregated to the level of 2,148 communities from swisstopo.

STATPOP

statpop2020 <- read_delim("data-raw/BfS-closed/STATPOP/statpop2020_220098p.zip", 
                          delim = ";", escape_double = FALSE, 
                          col_types = cols(STATYEAR = col_integer(), 
                                           SEX = col_integer(), 
                                           TYPEOFRESIDENCE = col_integer(), 
                                           POPULATIONTYPE = col_integer(), 
                                           AGE = col_integer(), 
                                           CLASSAGEFIVEYEARS = col_integer(), 
                                           NATIONALITYCATEGORY = col_integer(), 
                                           MAINRESIDENCECATEGORY = col_integer(), 
                                           GEOCOORDE = col_integer(), 
                                           GEOCOORDN = col_integer(), 
                                           INDIC_EGID = col_integer(), 
                                           statdate = col_date(format = "%d/%m/%Y")), 
                          trim_ws = TRUE) %>% 
  remove_empty(c("rows", "cols")) %>% clean_names()  

statpop2020_agg <- statpop2020 %>% 
  rename(egid = federalbuildingid) %>% 
  filter(typeofresidence == 1) %>% 
  filter(populationtype == 1) %>% 
  filter(mainresidencecategory == 1) %>% 
  filter(indic_egid == 1) %>% 
  select(-statyear, -statdate, 
         -typeofresidence, -populationtype, -mainresidencecategory,
         -indic_egid) %>% 
  group_by(egid, geocoorde, geocoordn) %>% 
  summarise(pop = n()) %>% 
  ungroup() %>% 
  st_as_sf(coords = c("geocoorde", "geocoordn"), 
           crs = 2056,
           remove = TRUE)

Using data from STATPOP 2020.

Dataset consists of 8,859,558 individuals and 1,549,502 buildings. We selected individuals with type of residence Hauptwohnsitz, pop type Ständige Wohnbevölkerung, main residency category Nur ein Hauptwohnsitz and with valid EGID building ID.

The nearest building with SSEP was assigned for each of these building. The point dataset was then overlaid with community boundaries and summary measures of pop based index were created and pop level SEP was aggregated by community.

’nhood based averages for communities

# # or with full version?
# st_gg <- st_read("data-raw/BfS/ag-b-00.03-875-gg/ggg_2021-LV95/shp/g1g21_01072021.shp",
#           as_tibble = TRUE)

ssep3_gem <- 
  st_join(sep3, 
          st_gg, 
          join = st_intersects) 

# tm_shape(gg) +
#   tm_polygons() +
#   tm_shape(ssep3_gem %>% filter(is.na(GMDNR))) +
#   tm_dots()

ssep3_gem_neigh <- ssep3_gem %>% 
  st_drop_geometry() %>% 
  group_by(GMDNR) %>% 
  summarise(n = n(),
            ssep3_median = median(ssep3)) %>% 
  ungroup() 

ssep3_gem_neigh_geo <- inner_join(gg, ssep3_gem_neigh) %>% 
  filter(!is.na(ssep3_median)) %>% 
  mutate(median_ssep3_d = ntile(ssep3_median, 10)) %>% 
  mutate(median_ssep3_d = factor(median_ssep3_d,
                                 levels = 1:10,
                                 labels = c("1st - lowest", 
                                            "2", "3", "4", 
                                            "5th decile", 
                                            "6", "7", "8", "9", 
                                            "10th - highest")))

write_rds(ssep3_gem_neigh_geo, "data/BfS/ssep3_gem_neigh_geo.rds")

Watch out for small n! Here some examples with communities below 20 n’hoods

Final map using median index - bubbles scaled to number of ’nhoods within community.

Population based averages for communities

# join to sep3
statpop2020_agg_sep <- st_join(statpop2020_agg, sep3, join = st_nearest_feature)

# # fails for unknown and unsolved reasons
# nearest <- st_nearest_feature(statpop2020_agg, sep3)
# statpop2020_agg_sep$dist3 <- st_distance(statpop2020_agg_sep, sep3[nearest, ], by_element = TRUE)
# rm(nearest, statpop2020_agg); gc()
# summary(statpop2020_agg_sep$dist3)

statpop2020_agg_sep_gem <- 
  st_join(statpop2020_agg_sep, st_gg, join = st_intersects) %>%  
  relocate(egid, gisid, pop,
           ssep3, ssep3_d,
           GMDNR) 

write_rds(statpop2020_agg_sep_gem, "data/BfS-closed/SEP/statpop2020_agg_sep_gem.Rds")
ssep3_gem_pop <- statpop2020_agg_sep_gem %>% 
  select(GMDNR, ssep3, pop) %>% 
  uncount(pop) %>% 
  group_by(GMDNR) %>% 
  summarise(pop = n(),
            ssep3_median = median(ssep3)) %>% 
  ungroup() 

# left_join(gg, ssep3_gem_pop) %>% 
#   filter(is.na(ssep3_median))

ssep3_gem_pop_geo <- 
  left_join(st_gg, ssep3_gem_pop) %>% 
  filter(!is.na(ssep3_median)) %>% 
  mutate(median_ssep3_d = ntile(ssep3_median, 10)) %>% 
  mutate(median_ssep3_d = factor(median_ssep3_d,
                                 levels = 1:10,
                                 labels = c("1st - lowest", 
                                            "2", "3", "4", 
                                            "5th decile", 
                                            "6", "7", "8", "9", 
                                            "10th - highest")))

write_rds(ssep3_gem_pop_geo, "data/BfS/ssep3_gem_pop_geo.rds")

Final map using median index - bubbles scaled to number of people (STATPOP 2020)

FIXME invalid geom?

Raumgliederungen

Data from the app. State as of 2021-07-01 to match spatial data nicely.

raum <- read_xlsx("data-raw/BfS/Raumgliederungen.xlsx", 
                  skip = 1) %>% 
  remove_empty(c("rows", "cols")) %>% clean_names() %>% 
  filter(! is.na(bfs_gde_nummer)) %>% 
  rename(GMDNR = bfs_gde_nummer,
         GMDNAME = gemeindename,
         KTNAME = kanton,
         BZNR = bezirks_nummer,
         BZNAME = bezirksname) %>% 
  select(GMDNR, GMDNAME, KTNAME, BZNR, BZNAME, 
         stadtische_landliche_gebiete, sprachgebiete,
         urbanisierungsgrad_2011_degurba_eurostat) %>% 
  mutate(
    r_urban1 = case_when(
      stadtische_landliche_gebiete == 1 ~  "Urban",
      stadtische_landliche_gebiete == 2 ~  "Periurban",
      stadtische_landliche_gebiete == 3 ~  "Rural",
      TRUE ~  ""),
    r_urban2 = case_when(
      urbanisierungsgrad_2011_degurba_eurostat == 1 ~  "Dense",
      urbanisierungsgrad_2011_degurba_eurostat == 2 ~  "Medium",
      urbanisierungsgrad_2011_degurba_eurostat == 3 ~  "Low",
      TRUE ~  ""),
    r_lang = case_when(
      sprachgebiete == 1 ~  "German",
      sprachgebiete == 2 ~  "French",
      sprachgebiete == 3 ~  "Italian",
      sprachgebiete == 4 ~  "Romansh",
      TRUE ~  "")
  ) %>% 
  select(-stadtische_landliche_gebiete, -sprachgebiete,
         -urbanisierungsgrad_2011_degurba_eurostat)

Urbanization 1

r_urban1 <character> 
# total N=2148 valid N=2148 mean=1.96 sd=0.69

Value     |    N | Raw % | Valid % | Cum. %
-------------------------------------------
Periurban |  562 | 26.16 |   26.16 |  26.16
Rural     | 1111 | 51.72 |   51.72 |  77.89
Urban     |  475 | 22.11 |   22.11 | 100.00
<NA>      |    0 |  0.00 |    <NA> |   <NA>

Urbanization 2

Using DEGURBA.

r_urban2 <character> 
# total N=2148 valid N=2148 mean=2.38 sd=0.57

Value  |    N | Raw % | Valid % | Cum. %
----------------------------------------
Dense  |   98 |  4.56 |    4.56 |   4.56
Low    | 1136 | 52.89 |   52.89 |  57.45
Medium |  914 | 42.55 |   42.55 | 100.00
<NA>   |    0 |  0.00 |    <NA> |   <NA>

Language region

r_lang <character> 
# total N=2148 valid N=2148 mean=1.79 sd=0.58

Value   |    N | Raw % | Valid % | Cum. %
-----------------------------------------
French  |  618 | 28.77 |   28.77 |  28.77
German  | 1390 | 64.71 |   64.71 |  93.48
Italian |  123 |  5.73 |    5.73 |  99.21
Romansh |   17 |  0.79 |    0.79 | 100.00
<NA>    |    0 |  0.00 |    <NA> |   <NA>

Voting

Data from swissdd package.

Linked to municipality boundaries from 2022-01-01.

st_gg <- read_rds("data/swisstopo/st_gg.Rds")

June vote

Bundesgesetz vom 25.09.2020 über die gesetzlichen Grundlagen für Verordnungen des Bundesrates zur Bewältigung der Covid-19-Epidemie (Covid-19-Gesetz)

Data

covid_jun <- get_nationalvotes(votedates = "2021-06-13", 
                               geolevel = "municipality") %>% 
  filter(str_detect(name, "Covid-19")) %>% 
  select(-name, -id)

Dataset consists of 2,141 communities.

Results preview

November vote

Änderung des Bundesgesetzes über die gesetzlichen Grundlagen für Verordnungen des Bundesrates zur Bewältigung der Covid-19-Epidemie (Covid-19-Gesetz) (Härtefälle, Arbeitslosenversicherung, familienergänzende Kinderbetreuung, Kulturschaffende, Veranstaltungen)

Data

covid_nov <- get_nationalvotes(votedates = "2021-11-28", 
                               geolevel = "municipality") %>% 
  filter(str_detect(name, "Covid-19")) %>% 
  select(-name, -id)

Dataset consists of 2,141 communities.

Results preview